-- UISkillEnergyBar
-- Create by zouyb Dec/14/2015
-- 技能能量槽界面
-- 该界面将作为子节点嵌在UIDungeonMain的skill_energy_bar节点下

local DARGON_MAGIC = -1;    -- 龙语魔法比较特殊，不属于神龙专属技能

UISkillEnergyBar = class("UISkillEnergyBar",function()
    return cc.Node:create();
end
);

function UISkillEnergyBar.create(heroId)
    return UISkillEnergyBar.new(heroId);
end

-- 构造函数
function UISkillEnergyBar:ctor(heroId)
    self.heroId = heroId;

    -- 初始化参数
    self:updateEnergy();

    if not self.maxEnergy then
        return;
    end

    -- 重绘
    self:redraw(heroId);

    -- 注册回调函数
    self:registerEventCallback();

    -- 注册点击处理
    self:registerTouchEvent();
end

-- 初始化参数
function UISkillEnergyBar:updateEnergy()
    -- 当前能量数
    self.curEnergy = 0;

    -- 最大能量数
    self.maxEnergy = 99;

    -- 更新当前能量
    self:updateCurEnergy();

    -- 更新最大能量数
    self:updateMaxEnergy();

    if self.curEnergy and self.maxEnergy then
        print("cur energy:" .. self.curEnergy .. ", max enerygy:" .. self.maxEnergy);
    end
end

-- 更新当前能量
function UISkillEnergyBar:updateCurEnergy()
    local specialSkillId = FormulaM.invoke("GET_SPECIAL_SLIME_SKILL", self.heroId);
    -- heroId == -1，说明是龙血,龙语魔法相关
    if self.heroId == DARGON_MAGIC then
        self.attrib = "dragon_blood";
        self.curEnergy = DungeonServiceM.queryDungeonAttrib(self.attrib);
    elseif specialSkillId then
        -- 主动技较特殊的冈布奥（皇后）
        local energyConfig = SlimeSkillM.calcUserEnergyCost(specialSkillId);
        local key = table.keys(energyConfig)[1];
        self.attrib = key;
        self.curEnergy = DungeonServiceM.queryDungeonAttrib(key);
    elseif not PetM.isSpecialPet(self.heroId) then
        -- 拥有主动专属技能的冈布奥
        local props = PropM.fetchProps(ME.user, "gain_slime_skill");
        for _, prop in ipairs(props) do
            local id = tonumber(prop[2]);
            if SlimeSkillM.query(id, "pet_id") == self.heroId then
                local energyConfig = SlimeSkillM.calcUserEnergyCost(id);
                local key = table.keys(energyConfig)[1];
                if type(key) ~= 'number' then
                    self.curEnergy = DungeonServiceM.queryDungeonAttrib(key);
                    self.attrib = key;
                    print("current energy: " .. self.curEnergy);
                end
            end
        end
    else
        -- 特殊冈布奥(世界树、收魂者、终结者)
        self.attrib = PetM.getAttribForSpecialPet(self.heroId);
        self.curEnergy = ME.user.dbase:query(self.attrib, 0);
    end
end

-- 更新最大能量数
function UISkillEnergyBar:updateMaxEnergy()
    if self.heroId == DARGON_MAGIC then
        self.maxEnergy = DungeonServiceM.getDungeonAttribInfo(self.attrib, "limit");
    elseif not PetM.isSpecialPet(self.heroId) then
        if self.attrib then
            self.maxEnergy = DungeonServiceM.getDungeonAttribInfo(self.attrib, "limit");
        end
    else
        if self.attrib == "vital_essence" then
            self.maxEnergy = PropM.combine(ME.user, "soul_to_item", 7158)[3] or 100;
        elseif self.attrib == "soul_collect" then
            self.maxEnergy = PropM.combine(ME.user, "soul_to_revive", 500)[3] or 100;
        elseif self.attrib == "opti_point" then
            self.maxEnergy = 100;
        end
    end
end

-- 重绘
function UISkillEnergyBar:redraw(heroId)
    local heroClassId = heroId;
    if heroId == DARGON_MAGIC then
        -- local pet = ME.user:getActivePet();
        -- 使用龙语魔法
        heroClassId = 21;
    end

    self:setCascadeOpacityEnabled(true);

    -- 英雄图标
    local fileName = PetM.getIcon(heroClassId);
    local iconPath = getSmallHeroIconPath(fileName);
    local hero = cc.Sprite:create(iconPath);
    hero:setScale(0.8);
    self:addChild(hero);

    -- 能量槽底图
    self.imageView = ccui.ImageView:create();
    self.imageView:loadTexture("images/ui/common/circle_gray.png");
    self.imageView:setTouchEnabled(true);
    self:addChild(self.imageView);

    -- 能量槽表面
    local fgPath = "images/ui/common/circle_red.png";
    local lightPath = "images/ui/common/circle_red_light.png";
    if PetM.isSpecialPet(heroClassId) then
        -- 特殊冈布奥使用蓝色能量条
        fgPath = "images/ui/common/circle_blue.png";
        lightPath = "images/ui/common/circle_blue_light.png";
    end

    self.progressBar = cc.ProgressTimer:create(cc.Sprite:create(fgPath));
    self.progressBar:setType(cc.PROGRESS_TIMER_TYPE_RADIAL);
    self.progressBar:setReverseDirection(true);
    self.progressBar:setPercentage(self.curEnergy / self.maxEnergy * 100);
    self:addChild(self.progressBar);

    -- 指示光
    self.lightParent = cc.Node:create();
    local light = ccui.ImageView:create();
    light:loadTexture(lightPath);
    light:setPosition(19, 0);

    -- 平时闪烁效果
    local action = cc.Sequence:create(cc.FadeTo:create(0.75, 102), cc.FadeTo:create(0.75, 255));
    light:runAction(cc.RepeatForever:create(action));

    self.lightParent:addChild(light);
    self.lightParent:setRotation(self:getDegree(self.progressBar:getPercentage()));
    self:addChild(self.lightParent);

    -- 有未处理的属性变化信息
    if self.attrib then
        local params = ME.user.dbase:queryTemp("temp_dungeon_attrib", self.attrib, false);
        if params then
            -- 更新进度条
            self:updateEnergyBar(params.from, params.to);
        end
    end

    if self.curEnergy >= self.maxEnergy then
        self:whenEnergyFull();
        self.lightParent:setVisible(false);
    end

    -- 更新列表
    self.updateList = {};
end

-- 设置透明度
function UISkillEnergyBar:setAlpha(opacity)
    self.opacity = opacity;

    self:setOpacity(opacity);

    if self.progressBar ~= nil then
        self.progressBar:setOpacity(opacity);
    end
end

-- 注册回调函数
function UISkillEnergyBar:registerEventCallback()
    -- 注册迷宫属性变化事件
    EventMgr.register("UISkillEnergyBar/"..self.heroId, event.DUNGEON_ATTRIB_CHANGE, function(params)
        if self.attrib ~= params.attrib then
            return;
        end

        -- 更新UI
        self:updateUI(params.from, params.to);
    end);

    -- 注册玩家信息更新的回调
    EventMgr.register("UISkillEnergyBar/"..self.heroId, event.USER_INFO_UPDATED, function(args)
        if self.attrib ~= args then
            return;
        end

        -- 更新UI
        self:updateUI(self.curEnergy, ME.user.dbase:query(self.attrib));
    end);

    -- 特殊冈布奥，关注灵魂收集和消耗事件
    -- 关注收集灵魂的事件
    EventMgr.register("UISkillEnergyBar/"..self.heroId, event.SOUL_COLLECT, function(params)
        if self.attrib ~= params.attrib then
            return;
        end

        -- 更新UI
        self:updateUI(self.curEnergy, self.curEnergy + params.amount);
        self:updateCurEnergy();
    end);

    -- 关注消耗灵魂的事件
    EventMgr.register("UISkillEnergyBar/"..self.heroId, event.SOUL_COST, function(params)
        if self.attrib ~= params.attrib then
            return;
        end

        --  有消耗， 更新最大值
        self:updateMaxEnergy();

        -- 更新UI
        self:updateUI(self.curEnergy, self.curEnergy - params.amount);
        self:updateCurEnergy();

        -- 是否有奖励
        self:whenGainBonus(params);
    end);

    self:registerScriptHandler(function(ev)
        if ev == "exit" then
            cclog("UISkillEnergyBar 界面析构清理");

            -- 反注册所有事件
            EventMgr.removeAll("UISkillEnergyBar/"..self.heroId);
        end
    end
    );
end

-- 清空事件回调
function UISkillEnergyBar:clearEventCallback()
    EventMgr.removeAll("UISkillEnergyBar/"..self.heroId);
end

-- 注册点击处理
function UISkillEnergyBar:registerTouchEvent()
    local function onClick(sender, eventType)
        if eventType ==  ccui.TouchEventType.ended then

            if self.heroId == DARGON_MAGIC then
                -- 打开龙语页
                UIDungeonMgr.getCurLevel():showMagicScrollUI(true);
                return;
            end

            -- 打开专属技信息
            local specialSkill = PetM.query(self.heroId, "special");
            local baseSkill = SkillM.findBaseSkill(specialSkill);
            local wakuseiSkill = WakuseiM.wakuseiSpecialSkill();

            if table.indexOf(wakuseiSkill, baseSkill) >= 0 then
                -- 变异体复制得到的，根据配置的宠物等级
                local petId = WakuseiM.queryByPetId(self.heroId, "skill_level_pet");
                local pet = PetM.getMyPet(petId);
                specialSkill = FormulaM.invoke("CALC_FINAL_SKILL", pet, specialSkill);
            else
                local hero = PetM.getMyPet(self.heroId);
                specialSkill = hero:getSpecial();
                specialSkill = FormulaM.invoke("CALC_FINAL_SKILL", hero, specialSkill);
            end

            if UIMgr.getCurrentScene():isOpen("UISkillOperation") then
                UIMgr.getCurrentScene():removeFormByName("UISkillOperation");
            end

            local uiSkillOperation = UISkillOperation.create(specialSkill, nil, self.heroId, true);
            UIMgr.getCurrentScene():addForm(uiSkillOperation);
            AudioM.playFx("market_open_child");
        end
    end
    self.imageView:addTouchEventListener(onClick);
end

function UISkillEnergyBar:getDegree(percent)
    return - percent * 360 / 100 - 90;
end

-- 更新UI
function UISkillEnergyBar:updateUI(from, to)
    -- 先缓存到更新列表
    table.insert(self.updateList, { from = from, to = to});

    --  播放节点
    if self.playNode == nil then
        self.playNode = cc.Node:create();
        self:addChild(self.playNode);
    end

    -- 播放效果
    local function play()
        if #self.updateList > 0 then
            local params = self.updateList[1];
            self.isPlaying = true;
            self:updateEnergyBar(params.from, params.to);
            local delay = 0.15;
            if params.to < params.from then
                delay = 0.5;
            end

            table.remove(self.updateList, 1);
            performWithDelay(self.playNode, play, delay);
        else
            self.isPlaying = false;
        end
    end

    if not self.isPlaying then
        play();
    end
end

-- 更新能量槽
function UISkillEnergyBar:updateEnergyBar(from, to)
    print("from:" .. from .. ", to:" .. to);

    if from == to then
        return;
    end

    local fromPercent = from / self.maxEnergy * 100;
    if fromPercent > 100 then
        fromPercent = 100;
    end

    self.progressBar:setPercentage(fromPercent);
    self.lightParent:setRotation(self:getDegree(fromPercent));

    -- 进度条变化
    local newPercent = (to / self.maxEnergy * 100);
    if newPercent > 100 then
        newPercent = 100;
    end

    local action = cc.ProgressTo:create(0.5, newPercent);
    self.progressBar:runAction(action);
    self.lightParent:stopAllActions();

    local rotate = cc.RotateTo:create(0.5, self:getDegree(newPercent));
    local callfunc = cc.CallFunc:create(function()
        if self.opacity then
            self:setAlpha(self.opacity);
        end
    end);
    self.lightParent:runAction(cc.Sequence:create(rotate, callfunc));

    -- 飘字
    if to > from then
        local deltaStr = "";
        local color;
        deltaStr = "+" .. tostring(to - from);
        color = TextStyleM.TEXT_COLOR_LIGHT_BLUE;

        local fontSize = 20;
        local text = TextPoolM.createTextObject(fontSize);
        text:setTextColor(color);
        TextStyleM.setOutlineStyle(text, nil, TextStyleM.TEXT_OUTLINE_COLOR);
        text:setPosition(2, 0);

        text:setString(deltaStr);
        self:addChild(text);

        local curScale = text:getScale();
        text:setScale(0.8 * curScale);
        local scaleUp = cc.ScaleTo:create(0.2, 1.2 * curScale);
        local scaleDown = cc.ScaleTo:create(0.15, 1.0 * curScale);
        local move = cc.MoveBy:create(1.0, cc.p(0, 30));
        local delay = cc.DelayTime:create(0.5);
        local fadeOut = cc.FadeOut:create(0.5);
        local callfunc = cc.CallFunc:create(function()
            self:removeChild(text);
            TextPoolM.freeTextObject(text);
        end);

        local action = cc.Sequence:create(scaleUp, scaleDown, cc.Spawn:create(move, cc.Sequence:create(delay, fadeOut)), callfunc);
        text:runAction(action);
   end

    -- 如果能量槽满
    if to >= self.maxEnergy then
        self:whenEnergyFull();
        self.lightParent:setVisible(false);
    else
        self:resetStatus();
    end

    -- 清除暂存信息
    ME.user.dbase:deleteTemp("temp_dungeon_attrib", self.attrib);
end

-- 重置状态
function UISkillEnergyBar:resetStatus()
    self:setOpacity(255);
    self.progressBar:setOpacity(255);
    self:stopAllActions();
    self.lightParent:setVisible(true);
    self:setScale(1);
end

-- 播放动画
function UISkillEnergyBar:whenEnergyFull()
    print("max energy")

    -- 轻微闪烁
    local scaleUp = cc.ScaleTo:create(0.5, 1.1);
    local scaleDown = cc.ScaleTo:create(0.5, 1);
    self:runAction(cc.RepeatForever:create(cc.Sequence:create(scaleUp, scaleDown)));

    -- -- 世界树冈布奥
    -- if self.attrib == "vital_essence" then

    --     -- 飞入效果
    --     local itemId = 7158;
    --     local amount = 1;
    --     local fileName = ItemM.query(itemId, "icon");
    --     local iconPath = getItemIconPath(fileName);
    --     local uiCurLevel = UIDungeonMgr.getCurLevel();
    --     local iconNode = uiCurLevel:getEquipNode();

    --     pickupPropertyEffect(self, iconNode, iconPath, itemId, amount);
    --     return;
    -- end
end

function UISkillEnergyBar:whenGainBonus(para)
    local bonus = para.bonus or {};
    local classId = bonus.classId;
    local amount = bonus.amount;

    if not classId or not amount then
        return;
    end

    -- 飞入效果
    local fileName = ItemM.query(classId, "icon");
    local iconPath = getItemIconPath(fileName);
    local uiCurLevel = UIDungeonMgr.getCurLevel();
    local iconNode = uiCurLevel:getEquipNode();

    pickupPropertyEffect(self, iconNode, iconPath, classId, amount);
end

